﻿using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Globalization;

namespace Isaac.Joy.StringHelper
{
    public sealed class MD5
	{
		private MD5() { }

		/// <summary>
		/// 对文本进行加密
		/// </summary>
		/// <param name="password">被加密文本</param>
		/// <returns>加密后文本</returns>
		public static string Encrypt(string password)
		{
			var returnValue = new StringBuilder();
			byte[] data = Encoding.Unicode.GetBytes(password);
			var md5 = new MD5CryptoServiceProvider();

			byte[] result = md5.ComputeHash(data);

			for (int j = 0; j < result.Length; j++)
			{
				returnValue.Append(result[j].ToString("X", CultureInfo.CurrentCulture).PadLeft(2, '0'));
			}

			return returnValue.ToString();
		}

		public static string GetMD5Hash(string input)
		{
			var returnValue = new StringBuilder();
			byte[] data = Encoding.Unicode.GetBytes(input);
			var md5 = new MD5CryptoServiceProvider();

			byte[] result = md5.ComputeHash(data);

			for (int j = 0; j < result.Length; j++)
			{
				returnValue.Append(result[j].ToString("x2", CultureInfo.CurrentCulture));
			}

			return returnValue.ToString();
		}

		public string GetMD5Hash(Stream stream)
		{
			var md5 = new MD5CryptoServiceProvider();
			byte[] retVal = md5.ComputeHash(stream);

			var sb = new StringBuilder();
			for (int i = 0; i < retVal.Length; i++)
			{
				sb.Append(retVal[i].ToString("x2"));
			}
			return sb.ToString();
		}

		/// <summary>
		/// MD5加密
		/// </summary>
		/// <param name="pToEncrypt"></param>
		/// <param name="sKey"></param>
		/// <returns></returns>
		public static string MD5Encrypt(string pToEncrypt, string sKey)
		{
			if (string.IsNullOrEmpty(pToEncrypt)) return string.Empty;

			var des = new DESCryptoServiceProvider();
			byte[] inputByteArray = Encoding.Default.GetBytes(pToEncrypt);
			des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
			des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
			var ms = new MemoryStream();
			var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
			cs.Write(inputByteArray, 0, inputByteArray.Length);
			cs.FlushFinalBlock();
            var ret = new StringBuilder();
			foreach (byte b in ms.ToArray())
			{
				ret.AppendFormat("{0:X2}", b);
			}

			return ret.ToString();


		}

		/// <summary>
		/// MD5解密
		/// </summary>
		/// <param name="pToDecrypt"></param>
		/// <param name="sKey"></param>
		/// <returns></returns>
		public static string MD5Decrypt(string pToDecrypt, string sKey)
		{
			if (string.IsNullOrEmpty(pToDecrypt)) return string.Empty;

            var des = new DESCryptoServiceProvider();

			byte[] inputByteArray = new byte[pToDecrypt.Length / 2];
			for (int x = 0; x < pToDecrypt.Length / 2; x++)
			{
				int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16));
				inputByteArray[x] = (byte)i;
			}

			des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
			des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
            var ms = new MemoryStream();
            var cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
			cs.Write(inputByteArray, 0, inputByteArray.Length);
			cs.FlushFinalBlock();

			return Encoding.Default.GetString(ms.ToArray());
		}
	}
}
